/******************************************************************************
*
*  NyMPh - Neeley's MP3 Player
*  Created by Patrick Neeley <patrick@neeley.org>
*             http://www.neeley.org/
*  Created on 2007.05.17
*  Updated on 2007.08.04
*
******************************************************************************/

import flash.MovieClip;
import flash.TextFormat;

class NyMPh
{
    // song list
  private static var g_SongList : SongList;

    // player
  private static var g_Player : PlayStrip;

    // number of songs displayed (for dynamic var names)
  private static var g_nCreated : Int = 1;

  private static var g_bEntered : Bool = false;

  private static var g_DownloadScript : String = "";
  private static var g_bAllowDownload : Bool = false;
  private static var g_bContinuousPlay : Bool = false;

  private static var g_JS : haxe.remoting.Connection = null;


  // FUNCTION: main
  //
  static function main ()
  {
      // We commit on the first call to onEnterFrame because we need to know
      // the stage size, and this is not available in some browsers until the 
      // first frame is loaded... and I think it's only an IE issue... go
      // figure.
    flash.Lib._root.onEnterFrame = function () {
      if (g_bEntered) {
        return;
      }
      g_bEntered = true;

        // read in the input variable named "pl", which contains the URL 
        // to the XML file that contains our playlist
      var playlist = flash.Lib._root.pl;

      if (playlist != "") {
          // load the playlist
        var _call = new haxe.Http(playlist);
          // call parseAndRun (below) if successful
        _call.onData = parseAndRun;
          // or die a tragic death
        _call.onError = function(error:String) {
          trace("Could not load playlist XML file ...");
        }
          // commit
        _call.request(false);
      }
    } // end root.onEnterFrame
  }
  //
  // end FUNCTION main


  // FUNCTION: parseAndRun
  //
  static function parseAndRun (the_data:String)
  {
      // for convenience:
    var root : MovieClip = flash.Lib._root;

      // if the XML file is empty, die
    if (the_data == "") {
      trace("Playlist could not be retrieved ...");
      return;
    }

      // set our stage scale to max and retrieve width and height
    root._alpha = 100;
    root._xscale = 100;
    root._yscale = 100;
    flash.Lib.current._xscale = 100;
    flash.Lib.current._yscale = 100;
    var w = flash.Stage.width;
    var h = flash.Stage.height;
    if (w <= 0) { w = root.w; }
    if (h <= 0) { h = root.h; }
    if (w <= 0) { w = 380; }
    if (h <= 0) { h = 228; }

      // parse our XML playlist
    var x : Xml = Xml.parse(the_data).firstElement();

      // get settings from XML data
    var plname = x.get("title");
    if (x.get("download") == "true") {
      g_bAllowDownload = true;
    }
    if (x.get("continuous") == "true") {
      g_bContinuousPlay = true;
    }
    g_DownloadScript = x.get("downloadscript");

    g_JS = haxe.remoting.Connection.jsConnect();

      // colors
    var ccolor = _getColorInt(x.get("color"), 0x000000);
    var ctext = _getColorInt(x.get("text"), 0xFFFFFF);
    var ccon = _getColorInt(x.get("concolor"), 0x000000);
    var ccontext = _getColorInt(x.get("context"), 0xFFFFFF);
    var ctrack = _getColorInt(x.get("trackcolor"), 0xFFFFFF);
    var ctracktext = _getColorInt(x.get("tracktext"), 0x000000);
    var ctrackhilite = _getColorInt(x.get("trackhilite"), 0xAFAFEF);
    var ctrackhilitetext = _getColorInt(x.get("trackhilitetext"), 0x000000);
    var clist = _getColorInt(x.get("listcolor"), 0xAFAFEF);
    var clistentry = _getColorInt(x.get("listentry"), 0xEFEFEF);
    var clisttext = _getColorInt(x.get("listtext"), 0x000000);

      // create our song list component
    g_SongList = new SongList(
      root, g_bAllowDownload, 4, 26, w - 8, h - 68,
      clist, clistentry, clisttext
    );
      // ... and make sure that the list updates the player
    g_SongList.onPlaySong = function (num:Int, file:String, title:String, dlfile:String) {
      g_Player.setSongFile(num, file, title, dlfile);
    }
    if (g_bAllowDownload) {
      g_SongList.onDownload = onDownloadHandler;
    }

      // create our song player component
    var psy = g_SongList.getY() + g_SongList.getHeight() + 4;
    g_Player = new PlayStrip(
      root, g_bAllowDownload, 4, psy, w - 8, h - psy - 4,
      ccon, ccontext, ctrack, ctracktext, ctrackhilite, ctrackhilitetext
    );

    g_Player.onSoundCompleteNotify = onSoundCompleteNotify;
    if (g_bAllowDownload) {
      g_Player.onDownload = onDownloadHandler;
    }

      // get and display our playlist title... for some reason (I don't know
      // why at the moment) this MUST be done AFTER the SongList and PlayStrip
      // are created, otherwise it won't display properly... weird
    var TitleDisplay : Component = new Component(root, true);
    TitleDisplay.setColor(ccolor);
    TitleDisplay.setTextColor(ctext);
    var tf:TextFormat = TitleDisplay.getTextFormat();
    tf.font = "Verdana,Arial,Helvetica";
    tf.bold = true;
    TitleDisplay.setTextFormat(tf);
    TitleDisplay.setNewTextFormat(tf);
    TitleDisplay.setText(plname);
    TitleDisplay.move(4,4,w-8,18);

    var LogoDisplay : Button = new Button(root, "nymphicon", false);
    LogoDisplay.move(w-5-16,5,16,16);
    LogoDisplay.onPress = LogoPressHandler;

      // loop through the "song" elements, displaying each as we go
    var n = 0;
    for (songNode in x.elementsNamed("song")) {
        // get the song information from the XML element
      var file = songNode.get("file");
      var title = songNode.get("title");
      var duration = songNode.get("duration");
      var dlfile = songNode.get("downloadurl");

        // add this song to the song list
      g_SongList.addSong(file, title, duration, dlfile);

      if (++n > 999) {
        break;
      }
    }
  }
  //
  // end FUNCTION parseAndRun


  function onSelectSongHandler (num:Int, file:String, title:String, dlfile:String) {
    g_Player.setSongFile(num, file, title, dlfile);
  }

  static function onSoundCompleteNotify (num:Int, file:String, title:String) {
    if (g_bContinuousPlay) {
      g_SongList.playNextEntry(num);
    }
  }

  static function onDownloadHandler (dlfile:String) {
    if (!g_bAllowDownload) {
      return;
    }
    if (dlfile != null && dlfile != "") {
      if (g_DownloadScript != null && g_DownloadScript != "") {
        dlfile = g_DownloadScript + dlfile;
      }
      g_JS.JSRemote.download.call([dlfile]);
    }
  }

  static function LogoPressHandler () {
    g_JS.JSRemote.download.call(["http://www.neeley.org/?con=software/flash"]);
  }


  static private function _getColorInt (s:String, ?cdefault:Int) : Int
  {
    if (s == null || s == "") {
      return cdefault;
    }
    s = s.toUpperCase();

    var ns:String = "";
    var ni:Int = 0;
    var i:Int = s.length - 1;
    var cp:Int = 0;
    while (i > -1 && cp < 6)
    {
      var c:String = s.charAt(i);
      --i;

      var cn:Int = -1;

      switch (c) {
        case "0": cn = 0;
        case "1": cn = 1;
        case "2": cn = 2;
        case "3": cn = 3;
        case "4": cn = 4;
        case "5": cn = 5;
        case "6": cn = 6;
        case "7": cn = 7;
        case "8": cn = 8;
        case "9": cn = 9;
        case "A": cn = 10;
        case "B": cn = 11;
        case "C": cn = 12;
        case "D": cn = 13;
        case "E": cn = 14;
        case "F": cn = 15;
      }

      if (cn > -1) {
        if (cp > 0 && cn > 0) {
          cn *= Std.int(Math.pow(16, cp));
        }
        ni += cn;
        ++cp;
      }
    }

    return (ni == null) ? cdefault: ni;
  }
}
// end class MP3Play
